#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#include<string.h>
#include<mpi.h>

# define qtde 65200
# define ALFABETO 26

typedef struct {
    char pal[30];
}palav;

// variaveis globais
unsigned ind_max = 0,ind_bas = 0;
int nachadas = 0;
palav dicionario[qtde];

void gera_aleatorio(char *word,int MAXPALAVRA){
	int i = 0;

	for(i=0;i<MAXPALAVRA; i++){
		word[i] = (rand()%ALFABETO) + 97;
	}
	word[MAXPALAVRA]='\0';
}
int busca_palavra(char *palavra){
	int i = 0;
	//printf("entrada %s\n", palavra);
	for(i=0;i<ind_max; i++){
	    //printf("dicionario[%d].pal =  %s\n",i, dicionario[i].pal);
		if(strcmp(dicionario[i].pal, palavra) == 0){
			return i;
		}
	}
	return -1;
}

int main (int argc, char *argv[]) {

	FILE * arqIn;
	clock_t fim, inicio;
	double tempo;
	int j,k;
	int encontrada[qtde];
	int descravo[qtde];
	int MAXPALAVRA = 2;

	char word[20];
	unsigned i=0;

	char *dbin = calloc(100,sizeof(char));
	// variaveis usadas para MPI
    int numprocs, rank, namelen, rc;
    char processor_name[MPI_MAX_PROCESSOR_NAME];

    MPI_Status Stat;
    rc = MPI_Init(&argc, &argv);

    if(rc != MPI_SUCCESS){
            printf("Falha ao iniciar MPI\n\n");
            exit(-1);
    }
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Get_processor_name(processor_name, &namelen);
    srand(time(NULL) + rank);

	inicio = clock();

	if(rank == 0){ //capataz
    	printf("Mestre\n");
		int found;

		for(k=1;k<numprocs;k++){
		    //recebe vetor de encontradas
			MPI_Recv(descravo, qtde, MPI_INT, k, 1, MPI_COMM_WORLD, &Stat);
			//concatena
			for(i=0;i<qtde;i++){
			    //se a palavra nao foi encontrada e o escravo encontrou
                if(encontrada[i] == 0 && descravo[i] == 1)
                    //muda para encontrado
                    encontrada[i] = 1;
			}
		}
		int total = 0;
		for(i=0;i<qtde;i++){
            if(encontrada[i] == 1)
                total++;
		}
		printf("Total encontradas %d\n",total);

    }else{//lacaios
        ind_max=0;
       /* if(rank == 1){
            MAXPALAVRA = 2;
        }*/
        for(j=2; j<4 ; j++){
            if(ind_max==0)
                ind_bas=ind_max;
            else
                ind_bas=ind_max - 1;
            nachadas = 0;
            //escreve o nome do arquivo em dbin
            sprintf(dbin,"0%d.txt", j);
            if(!(arqIn = fopen(dbin, "r"))){
                printf("Erro ao abrir o arquivo!\n\n");
                return -1;
            }

            while (!feof(arqIn)){
                //le palavras do dicionario
                fscanf(arqIn, "%s\n", dicionario[ind_max].pal);
                printf("\nWord = %s, ind max = %d,ind_bas = %d\n", dicionario[ind_max].pal,ind_max,ind_bas);
                //incrementa numero de palavras do dicionario
                ind_max++;
            }
            printf("Quantidade de palavras = %d\n", ind_max-ind_bas);

            fclose(arqIn);

            //inicia vetor de palavras encontradas (0 nao achou e 1 achou)
            for(i=ind_bas;i<ind_max;i++){
                encontrada[i] = 0;
            }
            for(i=ind_max;i<qtde;i++){
                encontrada[i] = -1;
            }
            int continua = 1;
            while(continua){
                //gera uma palavra aleatoria
                gera_aleatorio(word,MAXPALAVRA);
                //busca a palavra gerada no dicionario, se achar,
                //retorna o indice da palavra no dicionario
                int indice = busca_palavra(word);

                if(indice >= 0){//se encontrou a palavra no dicionario
                    if(encontrada[indice] == 0){//se a palavra ainda nao foi encontrada
                        printf("\nNo %d ACHEI = %s",rank,word);
                        encontrada[indice] = 1;//muda status para encontrada
                        nachadas++;//incrementa numero de achadas
                    }
                    if(nachadas == ind_max-ind_bas){//se achou todas as palavras de tamanho atual, termina e aumenta o tamanho
                        MAXPALAVRA++;
                        continua = 0;
                    }
                }
                fim = clock();
                tempo =((fim-inicio)/(CLOCKS_PER_SEC/1000));
                if(tempo > 10000){//se estourou o tempo e ms, termina o processo e envia dados para mestre
                    printf("\nEscravo %d tempo = %f\n", rank,tempo);
                    MPI_Send(encontrada, qtde, MPI_INT, 0, 1, MPI_COMM_WORLD);
                    return 0;
                }
            }//while
        }//for
    }//else -> escravo

	return 0;
}
